<template>
  <div>
    <h3>事件代理原理</h3>
    <!-- 性能优化考虑：v-for为每个循环项绑定事件，改为为其共同的父元素ul添加代理，这样就避免了为每个li都绑定一个事件，只需要
    提供点击事件的参数event,event.target可以拿到触发事件的事件源对象。注意：最后分支判断，过滤掉ul本身-->
    <ul @click="clickHandle">
      <li v-for="(item, index) in list" :key="item.id" :data-index="index">{{ item.name }}</li>
    </ul>
    <div id="fat">
      <p id="demo">请点击按钮来获得 fat 元素子节点的相关信息。</p>
      vue的template中空格childNodes属性获取不到
      <br />
      <button @click="myFunction" class="btn">试一下</button>
      <p>
        <b>注释：</b>
        元素中的空格被视为文本，而文本被视为节点。
      </p>
    </div>
  </div>
</template>
<script>
/**
 * 功能；点击每个li，弹出该li在列表中的索引值-事件委托来实现
 * 参考博客：https://blog.csdn.net/weixin_34281477/article/details/88940536?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242
 * 事件委托的作用：
 * 1.将事件处理程序代理到父节点，减少内存占用率
 * 2.动态生成子节点时，子节点自动将事件绑定到父节点上
 * 注意点：
 * 通过原生对象.nodeName属性，过滤掉ul父节点
 */
export default {
  data() {
    return {
      list: [{ id: 1, name: '张三' }, { id: 2, name: '李红' }, { id: 3, name: '洪福' }, { id: 4, name: '薛全奇' }, { id: 5, name: '赵毅' }]
    };
  },
  created() {
    console.log(this);
  },
  methods: {
    clickHandle(event) {
      console.log(event);
      console.log(event.target);
      // 过滤掉ul，不然会出现问题
      // nodeName 元素名，例如：LI 属性值 #text   #comment       #document
      // nodeType 1(元素),2（属性）,3（文本）,8（注释：comment）,9(document)
      // nodeValue null      属性值    3.文本：文本值  8.注释  注释的文本内容  9.document null
      /* event.target和event.currentTarget的区别和联系
      event.target是引起触发事件的那个对象
      event.currentTarget 当前事件执行时，所停留的那个对象
      */
      if (event.target.nodeName.toLowerCase() === 'li') {
        // event.target.dataset是一个对象 dataset: DOMStringMap {v-5487317c: "", index: "3"}
        console.log(event.target.dataset.index); // 结果是一个对象{index: 数字}
        var index = event.target.dataset.index;
        this.doSomething(index);
      }
    },
    doSomething(index) {
      alert(index);
    },
    myFunction() {
      var txt = '';
      /**
       * 特别注意：
       * 在vue的template模板中，和index.html中不一样。template模板中，原生对象的childNodes
       * 属性获取不到每行标签之间的空格，空格不会当作文本
       * 对比代码：https://www.w3school.com.cn/tiy/t.asp?f=jsref_node_nodename
       *
       *
       */
      var c = document.getElementById('fat').childNodes;
      console.log(c);
      for (var i = 0; i < c.length; i++) {
        txt = txt + c[i].nodeName + '<br/>';
      }
      // 将txt文本显示在p#demo文本内容中
      var demo = document.getElementById('demo');
      demo.innerHTML = txt;
      alert(c[0].nodeValue);
      // 这个是p 就是元素节点
      alert(c[1].nodeValue);
      // 这个是文本节点，也就是p中间的字。
      alert(c[2].nodeValue);
      alert(c[3].nodeValue);
      // 获取p#demo的属性节点
      console.log(demo.getAttributeNode('id').nodeName); // 验证结果：属性节点的nodeName 是属性名
    }
  }
};
</script>
<style lang="less" scoped>
ul {
  li {
    list-style: none;
    cursor: pointer;
  }
}
</style>
